# -*- coding: utf-8 -*-

 ###############################################
 ##                                             ##
 ##   Submódulo modelo                           ##
 ##   @ Módulo compras                           ##
 ##                                              ##
 ##   de la línea Básicos                        ##
 ##   de Críptidos Digitales                     ##
 ##   GPL (c)2008                                ##
  ##                                             ##
    ###############################################

# print (0), "  compras.manejador     begin"

import sys
from decimal import Decimal as dec
import datetime

import man

# from man import Acepcion, Atributo, AtributoProducto, Documento, Entidad, Operacion, PartidaDocumento, Proceso, Producto, Rol

from man import *

from sqlalchemy import desc, Table, Column, Index, Date, Integer, Numeric, Text, UniqueConstraint, ForeignKey, orm, sql

#~ from sqlalchemy.orm import mapper
#~ from sqlalchemy.sql import func

currentDate = datetime.date.today()

# session = session()


# print (0), "  compras.manejador       definitions"



tiposDocumentoG = []


def agrega(data):
    m = "compras.manejador.agrega()"
    # print (1), m, data

    ## Proceso
    if data['pedido'] != -1:
        pedido = damePedido(id=data['pedido'])
        # El status se actualiza al final

        operacion = operacionI(id=pedido.operacion_id)

        #! FALTA ACTUALIZAR STATUS A LAS PARTIDAS DEL PEDIDO
        proceso = procesoI(operacion_id=operacion.id)

    else:
        # Si no hay pedido se crea un Proceso nuevo
        # Se omite la fecha para que se capture el momento de captura
        proceso = Proceso(tipo=u'compra', status=u'abierto')
        man.session().add(proceso)
        man.session().flush()

    ## Operacion ( Entrada Inventarios )
    # Se crea despues de calcular el costoTotal

    ## Documento
    # el id de operacion se actualiza despues de crearla
    if data['pedido'] != -1:
        referencia = u'%s' % pedido.id
    else:
        referencia = u''
    documento = Documento(tipo_id=data['tipoDocumento_id'], folio=data['folio'], fecha=data['fecha'], rol_id=data['rol_id'], subtotal=data['subtotal'], descuento=data['descuento'], descuentoporcentaje=data['descuentoPorcentaje'], impuesto=data['impuesto'], impuestoporcentaje=data['impuestoPorcentaje'], total=data['total'], referencia=referencia, status=u'cerrado')

    man.session().add(documento)
    man.session().flush()

    costoTotal = dec("0.00")

    ## PARTIDAS
    for index, item in enumerate(data['partidas']):
        producto = productoI(id=item['producto_id'])

        holder = rolI(tipo=u'propio')

        acepcionLocal = dameAcepcion(rol_id=holder.id, producto_id=item['producto_id'])

        ## item['costo'] no se usa
        ## item['descuento'] es cero siempre
        costo = item['precio'] * (100-item['descuento'])/100 * (100-data['descuentoPorcentaje'])/100

        costoPromedio = (producto.actual*producto.costopromedio + item['cantidad']*costo)/(producto.actual+item['cantidad'])

        acepcionLocal.costo = costoPromedio

        producto.costopromedio = costoPromedio
        producto.actual += item['cantidad']

        ## Revisar Precios
        if atributoI(grupo=u'producto', nombre=u'recalcularPrecioAlComprar').valor == u'1':
            # print (2), m, "Revisando cambios de precios"
            margen = dec(atributoI(grupo=u'producto', nombre=u'margenDeCambio').valor)
            sentido = atributoI(grupo=u'producto', nombre=u'sentidoDeCambio').valor

            rangosPrecio = rangosPrecioI()
            for index, rango in enumerate(rangosPrecio):
                if rango.referencia[1]==u'a':
                    atributoCero = [x for x in producto.atributos if x.atributo_id==rango.id]
                    if atributoCero:
                        atributo = atributoCero[0]
                        precio = dec(atributo.valor)

                        margenNeto = ((100+producto.margen) * (100+dec(atributo.factor1))/100 * (100-dec(atributo.factor2))/100)-100

                        precioNuevo = acepcionLocal.costo * (100+dec(data['impuestoPorcentaje']))/100 * (100+margenNeto)/100

                        if sentido == u'+/-':
                            if precioNuevo < (precio - margen) or precioNuevo > (precio + margen):
                                actualizaAtributoProducto(id=atributo.id, valor="%s" % precioNuevo)
                                # atributo.valor = "%s" % precioNuevo
                                # session().flush()
                                # print (), "id", atributo.
                        elif sentido == u'+':
                            if precioNuevo > (precio + margen):
                                actualizaAtributoProducto(id=atributo.id, valor="%s" % precioNuevo)
                                # session().flush()

        ## Revisar cambios a acepciones
        # print (2), m, "Revisando cambios a acepciones"

        acepcion = acepcionI(producto_id=item['producto_id'], rol_id=data['rol_id'], codigo=item['codigo'], nombre=item['nombre'], costo=item['precio'], descuentogeneral=data['descuentoPorcentaje'], status=u'actual')

        # acepcion = acepcionExiste(producto_id=item['producto_id'], rol_id=data['rol_id'], status=u'actual')
        # if acepcion:
            # Si ya existe una acepción para este proveedor se checa si hay cambios
            # changed = False
            # codigo y nombre no se pueden modificar
            # if acepcion.costo != item['precio']:
                # changed = True
            # if acepcion.descuentoindividual != item['descuento']:
                # changed = True
            # if acepcion.descuentogeneral != data['descuentoPorcentaje']:
                # changed = True
            # if changed:
                # acepcion2 = Acepcion(producto_id=acepcion.producto_id, rol_id=acepcion.rol_id, codigo=acepcion.codigo, nombre=acepcion.nombre, costo=acepcion.costo, descuentoindividual=acepcion.descuentoindividual, descuentogeneral=acepcion.descuentogeneral, referencia=acepcion.referencia, status=u'obsoleta', fechaalta=acepcion.fechaalta, fechabaja=currentDate)
                # session().add(acepcion2)
                # acepcion.costo = item['precio']
                # acepcion.descuentoindividual = item['descuento']
                # acepcion.descuentogeneral = data['descuentoPorcentaje']
                # acepcion.fechaalta = currentDate
                # session().flush()
                # status = u"acepcion changed"
        # else:
            # Si no existe una acepción para este proveedor se crea con los
            # datos capturados
            # acepcion = Acepcion(producto_id=item['producto_id'], rol_id=data['rol_id'], codigo=item['codigo'], nombre=item['nombre'], costo=item['precio'], descuentoindividual=item['descuento'], descuentogeneral=data['descuentoPorcentaje'], status=u'actual', fechaalta=currentDate)
            # man.session().add(acepcion)
            # man.session().flush()
            # status = u"acepcion added"

        partida = PartidaDocumento(documento_id=documento.id, producto_id=item['producto_id'], cantidad=item['cantidad'], costo=item['precio'], precio=item['precio'], descuento=item['descuento'], impuesto=item['impuesto'], status=u'cerrada')
        documento.partidas.append(partida)
        man.session().add(partida)

        man.session().flush()

        costoTotal += item['cantidad'] * costo

    ## Operacion ( ya calculado el costoTotal )
    operacion = Operacion(cuenta=u"inventarios", tipo=u"entrada", fecha=data['fecha'], monto=costoTotal, status=u'cerrada')
    proceso.operaciones.append(operacion)
    man.session().add(operacion)
    man.session().flush()

    ## Documento ( se actualiza operacion_id )
    documento.operacion_id = operacion.id
    man.session().add(documento)

    vencimiento = data['fecha']
    if u'30 días' in data['condiciones']:
        vencimiento = data['fecha'] + datetime.timedelta(30)
    if u'15 días' in data['condiciones']:
        vencimiento = data['fecha'] + datetime.timedelta(30)
    if u'10 días' in data['condiciones']:
        vencimiento = data['fecha'] + datetime.timedelta(30)

    ## Pago
    if data['pago']:
        operacion = Operacion(cuenta=u'caja', tipo=u'pago', fecha=data['pago']['fecha'], monto=-data['pago']['total'], status=u'cerrada')
        proceso.operaciones.append(operacion)
        man.session().add(operacion)

        if data['pago']['tipo'] == u'efectivo':
            documento = Documento(operacion_id=operacion.id, tipo=data['pago']['tipo'], fecha=data['pago']['fecha'], rol_id=data['rol_id'], total=data['pago']['total'], subtotal=data['pago']['cambio'], status=u'cerrado')
            man.session().add(documento)

        elif data['pago']['tipo'] == u'cheque':
            cheque = Documento(operacion_id=operacion.id, tipo=data['pago']['tipo'], folio=data['pago']['numero'], fecha=data['pago']['fecha'], rol_id=data['rol_id'], total=data['pago']['total'], referencia=data['pago']['cuenta'], status=u'abierto')
            man.session().add(cheque)

        proceso.status = u'cerrado'
    else:
        operacion = Operacion(cuenta=u'por pagar', tipo=u'pago', fecha=data['fecha'], fecha2=vencimiento, monto=data['total'], status=u'abierta', comentarios=data['condiciones'])
        proceso.operaciones.append(operacion)
        man.session().add(operacion)

        proceso.status = u'abierto'

    ## Ajuste
    if data['ajuste']:
        if data['pago']:
            cuenta = u'caja'
        else:
            cuenta = u'por pagar'
        operacion = Operacion(cuenta=cuenta, tipo=u'abono por descuento', fecha=data['pago']['fecha'], monto=-data['pago']['monto'], status=u'cerrada', referencia=data['pago']['referencia'])
        session().add(operacion)
        proceso.operaciones.append(operacion)

        ajuste = Documento(operacion_id=operacion.id, tipo=data['ajuste']['tipoDocumento'], folio=data['ajuste']['folio'], fecha=data['ajuste']['fecha'], rol_id=data['rol_id'], total=data['ajuste']['monto'], status=u'cerrado')
        session().add(ajuste)

    # consolidaEntradas(documento.partidas)
    #~ cuenta = session().query(Atributo).filter(Atributo.referencia==u'1001').one().valor    # Cuenta de caja
    # operacion = Operacion(cuenta, currentDate, vencimiento, documento.id, data['total'], 'activa')
    # session().add(operacion)

    if data['pedido'] != -1:
        pedido.status = u'cerrado'
        man.session().add(pedido)

    if data['folio'] == dameFolio():
        modificaFolio(data['folio'])

    man.session().commit()

    return True


def actualizaAtributoProducto(**datos):
    anterior = atributoProductoI(id=datos['id'])
    nuevo = AtributoProducto(producto_id=anterior.producto_id, nombre=anterior.nombre, valor=anterior.valor, factor1=anterior.factor1, factor2=anterior.factor2, referencia=anterior.referencia, usuario=anterior.usuario, status=u'obsoleto', fechaalta=anterior.fechaalta, fechabaja=datetime.datetime.today())
    anterior.fechaalta = datetime.datetime.today()
    if 'valor' in datos.keys():
        anterior.valor = datos['valor']


def dameAtributo(**filtros):
    f=g
    #! obsoleto, use atributoI()
    registro = session().query(Atributo).filter_by(**filtros).one()
    return registro


def atributoProductoI(**filtros):
    registro = man.session().query(AtributoProducto).filter(AtributoProducto.id==filtros['id']).one()
    return registro


def consolidaEntradas(partidas):
    for registro in partidas:
        producto = dameProducto(id=registro.producto_id)
        if producto.actual:
            producto.actual += registro.cantidad
        else:
            producto.actual = registro.cantidad
    session().commit()


def acepcionExiste(**filtros):
    try:
        if 'codigo' in filtros.keys():
            registro = session().query(Acepcion).filter(Acepcion.codigo==unicode(filtros['codigo'])).filter(Acepcion.rol_id==filtros['rol_id']).filter(Acepcion.status==u'actual').one()
        else:

            registro = session().query(Acepcion).filter(Acepcion.producto_id==filtros['producto_id']).filter(Acepcion.rol_id==filtros['rol_id']).filter(Acepcion.status==u'actual').one()
        return registro
    except:
        return None


def dameAcepcion(**filtros):
    # try:
        if filtros.has_key('id'):
            registro = man.session().query(Acepcion).filter(Acepcion.id==filtros['id']).one()
        elif 'producto_id' in filtros.keys():
            registro = man.session().query(Acepcion).filter(Acepcion.producto_id==filtros['producto_id']).filter(Acepcion.rol_id==filtros['rol_id']).filter(Acepcion.status==u'actual').one()
        else:
            registro = session().query(Acepcion).filter(Acepcion.codigo==unicode(filtros['codigo'])).filter(Acepcion.rol_id==filtros['rol_id']).filter(Acepcion.status==u'actual').one()
        return registro
    # except:
        # raise Exception("\ncompras.manejador.dameAcepcion\nfiltros:%s\n%s" % (filtros, sys.exc_info()))


def dameAcepciones(**filtros):
    m = "compras.manejador.dameAcepciones()"
    # print (1), m, filtros

    if 'status' not in filtros.keys():
        filtros['status'] = u'actual'

    if 'linea' in filtros.keys():
        #! Esto debe ser hecho para linea
        clasificacion = filtros.pop('clasificacion')
        if 'nombre' in filtros.keys():
            registros = session().query(Acepcion).filter(Acepcion.rol_id==filtros['rol_id']).filter(sql.func.lower(Acepcion.nombre).like("%s%%" % filtros['nombre'])).filter(Acepcion.status==filtros['status']).filter(producto.clasificacion==clasificacion).order_by(Acepcion.nombre).all()
        elif 'codigo' in filtros.keys():
            registros = session().query(Acepcion).filter(Acepcion.rol_id==filtros['rol_id']).filter(sql.func.lower(Acepcion.codigo).like("%s%%" % filtros['codigo'])).filter(Acepcion.status==filtros['status']).filter(Producto.clasificacion==clasificacion).order_by(Acepcion.codigo).all()

    else:
        if 'nombre' in filtros.keys():
            registros = man.session().query(Acepcion).filter(Acepcion.rol_id==filtros['rol_id']).filter(sql.func.lower(Acepcion.nombre).like("%s%%" % filtros['nombre'])).filter(Acepcion.status==filtros['status']).join(Producto).join((Atributo, Atributo.id==Producto.tipo_id)).filter(Atributo.nombre!=u'Servicio').order_by(Acepcion.nombre).all()
        elif 'codigo' in filtros.keys():
            registros = session().query(Acepcion).filter(Acepcion.rol_id==filtros['rol_id']).filter(sql.func.lower(Acepcion.codigo).like("%s%%" % filtros['codigo'])).filter(Acepcion.status==filtros['status']).join(Producto).join((Atributo, Atributo.id==Producto.tipo_id)).filter(Atributo.nombre!=u'Servicio').order_by(Acepcion.codigo).all()

    return registros


def dameBancos():
    f=g
    #! obsoleto, use rol() con tipo='banco'
    registros = session().query(Atributo).filter(Atributo.propietario==u'bancos').filter(Atributo.nombre==u'nombre').order_by(Atributo.valor).all()
    registros = [x.valor for x in registros]
    return registros


def dameClasificaciones():
    registros = atributosI(grupo=u'clasificacionProducto', order=u'nombre')
    return registros


def condicionesPago():
    registros = atributosI(grupo=u'condicionesPago')
    return registros


def dameCuentas():
    holder = rolI(tipo=u'propio')
    cuentas = [x for x in holder.atributos if x.nombre==u'cuenta']
    for cuenta in cuentas:
        cuenta.banco = rolI(id=int(cuenta.referencia))
    return cuentas



def documentoI(**filtros):
    m = "compras.manejador.documentoI()"
    print (1), m, filtros

    if 'id' in filtros.keys():
        registro = man.session().query(Documento).filter(Documento.id==filtros['id']).one()
    elif 'tipo' in filtros.keys():
        tipo = man.session().query(Atributo).filter(Atributo.grupo==u'tipoDocumento').filter(Atributo.nombre==filtros['tipo']).one()

        operaciones = man.session().query(Proceso).filter(Proceso.id==filtros['proceso_id']).one().operaciones

        registro = man.session().query(Documento).filter(Documento.tipo_id==tipo.id).filter(Documento.operacion_id.in_([x.id for x in operaciones])).one()
    else:
        registro = man.session().query(Documento).filter_by(**filtros).first()

    return registro


def dameDocumentos(**filtros):  # print "compras.manejador.dameDocumentos()"
    if filtros:
        if filtros.has_key('rol_id'):
            if filtros.has_key('status'):
                registros = session().query(Documento).filter(Documento.tipo.in_([u'factura', u'remisión'])).join(Proceso).filter(sql.func.lower(Proceso.tipo)==u'compra').filter(Documento.rol_id==filtros['rol_id']).filter(Proceso.status.in_(filtros['status'])).order_by(Documento.fecha.desc()).all()
            else:
                registros = session().query(Documento).filter(Documento.tipo.in_([u'factura', u'remisión'])).join(Proceso).filter(sql.func.lower(Proceso.tipo)==u'compra').filter(Documento.rol_id==filtros['rol_id']).order_by(Documento.fecha.desc()).all()
        # elif filtros.has_key('proceso_id'):
            # registros = session().query(Documento).join(Operacion).filter(Operacion.proceso_id==filtros['proceso_id']).order_by(Documento.fecha.desc()).all()
        else:
            if filtros.has_key('status'):
                registros = session().query(Documento).filter(Documento.tipo.in_([u'factura', u'remisión'])).join(Proceso).filter(sql.func.lower(Proceso.tipo)==u'compra').filter(Proceso.status.in_(filtros['status'])).order_by(Documento.fecha.desc()).all()
            else:
                registros = session().query(Documento).filter_by(**filtros).order_by(Documento.fecha.desc()).all()
    else:
        registros = session().query(Documento).filter(Documento.tipo.in_([u'factura', u'remisión'])).join(Proceso).filter(sql.func.lower(Proceso.tipo)==u'compra').order_by(Documento.fecha.desc()).all()
    return registros


def dameFolio():
    folio = int(atributoI(grupo=u'folioDocumento', nombre=u'compra').valor)
    folio += 1
    return unicode(folio).zfill(4)


def formasPagoI():
    registros = atributosI(grupo=u'formaPago', order=u'referencia')
    return registros


def lineas(**filtros):
    """ Filtra por referencia """
    if 'referencia' in filtros.keys():
        lineas = atributosI(grupo=u'lineaProducto', referencia=filtros['referencia'], order=u'nombre')
    else:
        lineas = atributosI(grupo=u'lineaProducto', order=u'nombre')
    return lineas


def operacionI(**filtros):
    if 'id' in filtros.keys():
        registro = man.session().query(Operacion).filter(Operacion.id==filtros['id']).one()
    elif 'cuenta' in filtros.keys():
        registro = man.session().query(Operacion).filter(Operacion.cuenta==filtros['cuenta']).filter(Operacion.documento_id==filtros['documento_id']).first()
    elif 'proceso_id' in filtros.keys():
        proceso = man.session().query(Proceso).filter(Proceso.id==filtros['proceso_id']).one()
        registroZero = [x for x in proceso.operaciones if x.tipo==filtros['tipo']]
        if registroZero:
            registro = registroZero[0]
    else:
        registro = man.session().query(Operacion).filter_by(**filtros).one()
    return registro


def dameOperaciones(**filtros): # print "compras.manejador.dameOperaciones()"
    if 'proceso_id' in filtros.keys():
        links = [x[0] for x in man.session().execute("SELECT operacion_id FROM proceso_operacion WHERE proceso_id=%s" % filtros['proceso_id'])]
        # links = session().execute("SELECT operacion_id FROM proceso_operacion WHERE proceso_id=%s" % filtros['proceso_id'])
        registros = man.session().query(Operacion).filter(Operacion.id.in_(links)).all()
        # registros = session().query(Operacion).filter(Operacion.procesos.any(Proceso.id==filtros['proceso_id'])).all()
    else:
        registros = man.session().query(Operacion).filter_by(**filtros).all()
    return registros


def damePagos(**filtros):
    registro = man.session().query(Operacion).filter(Operacion.cuenta==u'pagos').filter(Operacion.documento_id==filtros['documento_id']).all()
    return registro


def damePartidas(**filtros):
    registros = man.session().query(PartidaDocumento).filter_by(**filtros).all()
    return registros


def damePedido(**filtros):
    if filtros.has_key('id'):
        registro = man.session().query(Documento).filter(Documento.id==filtros['id']).one()
    elif filtros.has_key('proceso_id'):
        registro = session().query(Documento).filter(Documento.tipo==u'pedido').filter(Documento.proceso_id==filtros['proceso_id']).first()
    elif filtros.has_key('sinCompra'):
        registro = session().query(Documento).filter(Documento.tipo==u'pedido').filter(sql.func.lower(Documento.status)==u'abierto').first()
    return registro


def damePedidos(**filtros):
    tipoDocumento_id = atributoI(grupo=u'tipoDocumento', nombre=u'pedido')
    if 'rol_id' in filtros.keys():
        if 'sinCompra' in filtros.keys():
            registros = man.session().query(Documento).filter(Documento.tipo==tipoDocumento_id).filter(Documento.rol_id==filtros['rol_id']).filter(sql.func.lower(Documento.status)!=u'cerrado').all()
        else:
            registros = session().query(Documento).filter(Documento.tipo==tipoDocumento_id).filter(Documento.rol_id==filtros['rol_id']).all()
    else:
        if 'sinCompra' in filtros.keys():
            registros = man.session().query(Documento).filter(Documento.tipo==tipoDocumento_id).filter(sql.func.lower(Documento.status)!=u'cerrado').all()
        else:
            registros = session().query(Documento).filter(Documento.tipo==tipoDocumento_id).all()
    return registros


def procesoI(**filtros):
    m = "compras.manejador.procesoI()"
    if 'id' in filtros.keys():
        registro = man.session().query(Proceso).filter(Proceso.id==filtros['id']).one()
    elif 'documento_id' in filtros.keys():
        documento = documentoI(id=filtros['documento_id'])
        registro = man.session().query(Proceso).filter(Proceso.operaciones.any(id=documento.operacion_id)).one()
    else:
        registro = man.session().query(Proceso).filter(Proceso.operaciones.any(id=filtros['operacion_id'])).one()
    return registro


def dameProcesos(**filtros):    # print "compras.manejador.dameProcesos()"
    #! status es de documento, ¿Para procesos es igual?
    if 'status' in filtros.keys():
        if 'rol_id' in filtros.keys():
            registros = session().query(Proceso).filter(Proceso.tipo==filtros['tipo']).filter(Proceso.status==filtros['status']).join(Documento).filter(Documento.rol_id==filtros['rol_id']).order_by(Proceso.fecha).all()
        else:
            registros = man.session().query(Proceso).filter(Proceso.tipo==filtros['tipo']).filter(Proceso.status==filtros['status']).order_by(Proceso.fecha).all()
    else:
        if 'rol_id' in filtros.keys():
            registros = man.session().query(Proceso).filter(Proceso.tipo==u'compra').filter(Proceso.operaciones.any(Operacion.documentos.any(Documento.rol_id==filtros['rol_id']))).order_by(Proceso.fecha).all()
            # registros = session().query(Proceso).filter(Proceso.tipo==u'Compra').filter(Proceso.operaciones.rol_id==filtros['rol_id']).order_by(Proceso.fecha).all()
        else:
            registros = man.session().query(Proceso).filter(Proceso.tipo==u'compra').order_by(Proceso.fecha).all()
    return registros


def dameProveedores():
    tipo_id = atributoI(grupo=u'tipoRol', nombre=u'proveedor').id
    registros = man.session().query(Rol).filter(Rol.tipo_id==tipo_id).join(Entidad).order_by(Entidad.nombre).all()
    return registros


def rangosPrecioI():
    registros = atributosI(grupo=u'rangoPrecioProducto', order=u'referencia')
    # registros = atributos(grupo=u'productos', nombre=u'rangoPrecio', order=u'referencia')
    return registros


def dameRol(**filtros):
    f=g
    #! obsoleto, use rol()
    if 'id' in filtros.keys():
        registro = session().query(Rol).filter(Rol.id==filtros['id']).one()
    elif 'tipo' in filtros.keys():
        registro = session().query(Rol).filter(Rol.tipo==filtros['tipo']).one()
    return registro


def dameTiposDocumentoAjuste():
    registros = atributosI(grupo=u'tipoDocumento', referencia=u'ajustes')
    return registros


def tipoDocumentoDefault():
    registro = atributoI(grupo=u'tipoDocumentoCompra', nombre=u'default')
    registro = atributoI(id=int(registro.valor))
    return registro


def tiposDocumento():
    global tiposDocumentoG
    if not tiposDocumentoG:
        tiposDocumentoG = man.session().query(Atributo).filter(Atributo.grupo==u'tipoDocumento').filter(Atributo.referencia.like(u'%compra%')).all()
    return tiposDocumentoG


def formasPago():
    registros = atributosI(grupo=u'formaPago')
    return registros


def elimina(**filtros):
    registro = session().query(Documento).filter(Documento.id==filtros['id']).one()
    session().delete(registro)
    session().commit()


def folioExiste(*args):
    registro = man.session().query(Documento).filter(Documento.folio==args[0]).filter(Documento.rol_id==args[1]).join(Operacion).filter(Operacion.tipo==u'entrada').first()
    if registro:
        return registro.id
    else:
        return False


def modifica(data):
    m = "compras.manejador.modifica()"
    # print (1), m, data

    """ Se carga el proceso y todo se realiza sobre este registro """
    proceso = procesoI(id=data['proceso_id'])

    if 'documento' in data.keys():
        documento = dameDocumento(id=data['documento'].pop('id'))
        documento.setData(**data['documento'])
        man.session().add(documento)
        man.session().flush()

    if 'pago' in data.keys():
        """ 1) Una operacion de pago puede servir a dos procesos diferentes
            2) Un documento NO puede servir a dos operaciones diferentes
        """

        operacionPagoCero = [x for x in proceso.operaciones if x.tipo==u'pago']

        if operacionPagoCero:
            operacionPago = operacionPagoCero[0]

            if 'tipo' in data['pago'].keys():
                data['pago']['tipo_id'] = man.atributoI(grupo=u'tipoDocumento', nombre=data['pago'].pop('tipo')).id

            if 'cambio' in data['pago'].keys():
                data['pago']['subtotal'] = data['pago'].pop('cambio')

            if 'cuenta' in data['pago'].keys():
                data['pago']['referencia'] = data['pago'].pop('cuenta')

            if 'numero' in data['pago'].keys():
                data['pago']['folio'] = data['pago'].pop('numero')

            if operacionPago.documentos:
                documento = operacionPago.documentos[0]
                documento.setData(**data['pago'])
                man.session().add(documento)
            else:
                documento = Documento(**data['pago'])
                operacionPago.documentos.append(documento)
                man.session().add(documento)

            operacionPago.status = u'cerrada'

            proceso.status = u'cerrado'

            man.session().flush()
        else:
            """ 3) No existe Operacion, ya existe Documento """

            """ Este método se incluye por compatibilidad, se supone que la
                operación de pago ya debe estar capturada, sea en la cuenta
                Caja o en la cuenta Por pagar"""

            documentoPago = dameDocumento(tipo=data['pago']['tipo'], folio=data['pago']['folio'], rol_id=data['pago']['rol_id'])

            if documentoPago:
                proceso.operaciones.append(documentoPago.operacion)
                man.session().flush()
            else:
                """ 4) No existe Operacion, no existe documento """
                operacionPago = Operacion(tipo=u'pago', cuenta=u'caja', fecha=data['pago']['fecha'], monto=data['pago']['total'], status=u'cerrada')
                man.session().flush()

                banco = rol(tipo=u'banco', funcion=u'Banco', alias=data['pago']['referencia'])
                data['pago']['rol_id'] = banco.id
                documentoPago = Documento(**data['pago'])
                documentoPago.operacion_id = operacionPago.id
                man.session().flush()

                proceso.operaciones.append(operacionPago)
                man.session().flush()

    if 'ajuste' in data.keys():
        if 'id' in data['ajuste'].keys():   ## Puede no existir este documento
            ajuste = dameDocumento(id=data['ajuste'].pop('id'))
            ajuste.update(**data['ajuste'])
        else:
            pago = [x for x in proceso.operaciones if x.tipo==u'Pago'][0]

            operacion = Operacion(tipo="Abono por descuento", cuenta=pago.cuenta, fecha=data['ajuste']['fecha'], monto=-data['ajuste']['total'], status=u'cerrada')
            man.session().add(operacion)
            man.session().flush()
            proceso.operaciones.append(operacion)

            data['ajuste']['operacion_id'] = operacion.id

            ajuste = Documento(**data['ajuste'])
            session().add(ajuste)

    man.session().commit()


def modificaFolio(folio):
    try:
        # int(folio)
        registro = atributoI(grupo=u'folioDocumento', nombre=u'compra', valor=folio)
        # registro.valor = unicode(folio)
        # session().add(registro)
        # session().commit()
    except:
        pass

def operacionExiste(**filtros):
    registro = session().query(Operacion).filter(Operacion.cuenta==filtros['cuenta']).filter(Operacion.referencia==filtros['referencia']).first()
    return registro


def pagoExiste(**filtros):
    try:
        registro = session().query(Pago).filter(Pago.documento_id==filtros['documento_id']).one()
        return True
    except:
        return False




def totalDeCompras():
    return man.session().query(sql.func.count(Proceso.id)).filter(Proceso.tipo==u'compra').one()[0]

def totalDeProductos():
    return man.session().query(sql.func.count(Producto.id)).one()[0]

def totalDeProveedores():
    tipo_id = atributoI(grupo=u'tipoRol', nombre=u'proveedor').id
    return man.session().query(sql.func.count(Rol.id)).filter(Rol.tipo_id==tipo_id).one()[0]



pagos = Table('pagos', backend.metadata,
Column('id', Integer, primary_key=True),
Column('documento_id', Integer, ForeignKey('documentos.id')),
Column('tipo_id', Integer, ForeignKey('atributos.id')),
Column('fecha', Date),
Column('monto', Numeric),
Column('referencia', Text),
Column('dato1', Text))

class Pago(object):
    def __init__(self, *args, **kwds):
        if kwds.has_key('id'):              self.id = kwds['id']
        if kwds.has_key('documento_id'):    self.documento_id = kwds.pop('documento_id')
        if kwds.has_key('tipo_id'):         self.tipo_id = unicode(kwds.pop('tipo_id'))
        if kwds.has_key('fecha'):           self.fecha = kwds.pop('fecha')
        if kwds.has_key('monto'):           self.monto = kwds.pop('monto')
        if 'referencia' in kwds.keys():     self.referencia = kwds.pop('referencia')
        if kwds.has_key('dato1'):           self.dato1 = kwds.pop('dato1')

    def __repr__(self):
        return (u"<Pago (id:%s, documento_id:%s, tipo_id:%s, fecha:%s, monto:%s, referencia:%s, dato1:%s)>" % (self.id, self.documento_id, self.tipo_id, self.fecha, self.monto, self.referencia, self.dato1)).encode('utf-8')

orm.mapper(Pago, pagos)




def inicializa():
    backend.metadata.create_all(engine)
    # try:
        # version = int(atributoI(grupo=u'pago', nombre=u'versionBasedatos').valor)
    # except:
        # print "Inicializando Base de datos de Pagos"


        # atributoI(grupo=u'pago', nombre=u'versionBasedatos', valor=u'3')
        # version = 3
        # session().commit()





if __name__ == "__main__":
    pass



# print (0), "  compras.manejador     end"


"""
Lógica para el manejo de acepciones [20 Abr 2010]

La captura de acepciones evitará modificar datos ya existentes.

Se llevarán dos registros de las acepciones capturadas, uno para las capturadas por acepción local, y otro para las capturadas por acepción de proveedor.

Las partidas del documento guardan sólo las referencias a las acepciones del proveedor, no los textos, por lo que no se podrán utilizar acepciones temporales o por evento.

Si un artículo no cuenta con una acepción del proveedor, la rutina de registro la creará a partir de los textos recibidos, esta es la única modificación que se podrá realizar.

En los widgets de captura, la selección de un artículo se puede realizar mediante cualquier acepción registrada, cualquiera.

Independientemente del origen que se haya seleccionado, se identifica el producto y se guardan los textos de la acepción local.

En caso de que se haya seleccionado un proveedor para el documento, se busca la acepción para ese proveedor, si existe, se guarda, y es la que se muestra, si no existe, se guarda los textos de la acepción que se utilizó para identificar el artículo, y serán los que se usarán para crear la acepción para el proveedor seleccionado.

#!
Si no existe acepción para un artículo capturado, se deberá permitir la modificación de los textos, para que se cree la acepción con los textos adecuados.


"""